﻿using Identity.API.Data;
using Identity.API.Models;
using IdentityServer4.EntityFramework.DbContexts;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using System;
using System.IO;

namespace Identity.API
{
    public class Program
    {
        public static readonly string ConfigurationJson = "appsettings.json";
        public static readonly string Namespace = typeof(Program).Namespace;
        public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
        public static void Main(string[] args)
        {
            var configuration = GetConfiguration();
            Log.Logger = CreateSerilogLogger(configuration);
            //迁移数据库上下文
            try
            {
                Log.Information("Configuring web host ({ApplicationContext})...", AppName);
                var host = BuildWebHost(configuration, args);
                host.MigrateDbContext<PersistedGrantDbContext>((_, __) => { })
                    .MigrateDbContext<ApplicationDbContext>((context, services) =>
                     {
                         var env = services.GetService<IWebHostEnvironment>();
                         var logger = services.GetService<ILogger<ApplicationDbContextSeed>>();
                         var settings = services.GetService<IOptions<AppSettings>>();
                         var userManage = services.GetService<UserManager<ApplicationUser>>();
                         new ApplicationDbContextSeed()
                             .SeedAsync(context, env, logger, settings, userManage)
                             .Wait();
                     })
                    .MigrateDbContext<ConfigurationDbContext>((context, services) =>
                    {
                        new ConfigurationDbContextSeed()
                            .SeedAsync(context, configuration)
                            .Wait();
                    });
                Log.Information("Starting web host ({ApplicationContext})...", AppName);
                host.Run();
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }
        private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
         WebHost.CreateDefaultBuilder(args)
             .CaptureStartupErrors(false)
             .ConfigureAppConfiguration(x => x.AddConfiguration(configuration))
             .UseStartup<Startup>()
             .UseContentRoot(Directory.GetCurrentDirectory())
             .UseSerilog()
             .Build();
        private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
        {
            var seqServerUrl = configuration["Serilog:SeqServerUrl"];
            var logstashUrl = configuration["Serilog:LogstashgUrl"];
            return new LoggerConfiguration()
                .MinimumLevel.Verbose()
                .Enrich.WithProperty("ApplicationContext", AppName)
                .Enrich.FromLogContext()
                .WriteTo.Console()
                .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
                .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl)
                .WriteTo.RollingFile(configuration["Serilog:RollingFile"])
                .ReadFrom.Configuration(configuration)
                .CreateLogger();
        }
        private static IConfiguration GetConfiguration()
        {
            var builder = new ConfigurationBuilder()
                 .SetBasePath(Directory.GetCurrentDirectory())
                 .AddJsonFile(ConfigurationJson, optional: false, reloadOnChange: true)
                 .AddEnvironmentVariables();
            var config = builder.Build();
            if (config.GetValue<bool>("UseVault", false))
            {
                builder.AddAzureKeyVault(
                    $"https://{config["Vault:Name"]}.vault.azure.net/",
                    config["Vault:ClientId"],
                    config["Vault:ClientSecret"]);
            }
            return builder.Build();
        }
        /*
        public static void Main(string[] args)
        {
            //迁移数据库上下文
            BuildWebHost(args)
                .MigrateDbContext<PersistedGrantDbContext>((_, __) => { })
                 .MigrateDbContext<ApplicationDbContext>((context, services) =>
                 {
                     var env = services.GetService<IHostingEnvironment>();
                     var logger = services.GetService<ILogger<ApplicationDbContextSeed>>();
                     var settings = services.GetService<IOptions<AppSettings>>();
                     var userManage = services.GetService<UserManager<ApplicationUser>>();
                     new ApplicationDbContextSeed()
                         .SeedAsync(context, env, logger, settings, userManage)
                         .Wait();
                 })
                .MigrateDbContext<ConfigurationDbContext>((context, services) =>
                {
                    var configuration = services.GetService<IConfiguration>();
                    new ConfigurationDbContextSeed()
                        .SeedAsync(context, configuration)
                        .Wait();
                }).Run();
        }
        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .ConfigureAppConfiguration((builderContext, config) =>
            {
                var builtConfig = config.Build();
                var configurationBuilder = new ConfigurationBuilder();
                if (Convert.ToBoolean(builtConfig["UseVault"]))
                {
                    configurationBuilder.AddAzureKeyVault(
                        $"https://{builtConfig["Vault:Name"]}.vault.azure.net/",
                        builtConfig["Vault:ClientId"],
                        builtConfig["Vault:ClientSecret"]);
                }
                configurationBuilder.AddEnvironmentVariables();
                //config.AddConfiguration(configurationBuilder.Build()); 2019.3.3
                ///////2019.3.3///////
                if(builderContext.HostingEnvironment.EnvironmentName == "Development")
                {
                    config.SetBasePath(System.IO.Directory.GetCurrentDirectory())
                          .AddJsonFile("appsettings.Development.json", true, true)
                          .AddEnvironmentVariables();
                }
                else
                {
                    config.SetBasePath(System.IO.Directory.GetCurrentDirectory())
                        .AddJsonFile("appsettings.Production.json", true, true)
                        .AddEnvironmentVariables();
                }
                config.AddConfiguration(configurationBuilder.Build());
                //////////////////////
            })
            .ConfigureLogging((hostingContext, builder) =>
            {
                builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                builder.AddConsole();
                builder.AddDebug();
                builder.AddFilter("System", LogLevel.Warning);
                builder.AddFilter("Microsoft", LogLevel.Warning);
                builder.AddLog4Net();
            })
            .UseApplicationInsights()
            .UseSerilog((builderContext, config) =>
                {
                    config
                        .MinimumLevel.Information()
                        .Enrich.FromLogContext()
                        .WriteTo.Console();
            }).Build();
        */
    }
}
